package com.dragon.mmochat.service;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dragon.mmochat.MmochatConstant;
import com.dragon.mmochat.MmochatMain;
import com.dragon.mmochat.message.Mmochat_13_13S;
import com.dragon.mmochat.message.Mmochat_13_5C;
import com.dragon.mmochat.message.Mmochat_6_23C;
import com.dragon.mmochat.message.Mmochat_SendSuggestAward;
import com.dragon.mmochat.model.enumType.MmochatBigMoneyEarnType;
import com.dragon.mmochat.model.enumType.MmochatPayLotteryState;
import com.dragon.mmochat.model.enumType.MmochatPropType;
import com.dragon.mmochat.model.enumType.MmochatWorkStationType;
import com.dragon.mmochat.model.object.MmochatPropEffect;
import com.dragon.mmochat.model.role.MmochatPlayer;
import com.dragon.mmochat.util.MmochatUtil;
import com.skymobi.handler.SkymobiHandler;
import com.skymobi.message.SkymobiProtocolMessage;
import com.skymobi.message.currency.DirectChargeNotice;
import com.skymobi.message.currency.DirectChargeResult;
import com.skymobi.message.currency.DirectChargeNotice.ResultCode;
import com.skymobi.service.SkymobiService;
import com.skymobi.service.currency.ChargeNoticeProcessor;
import com.skymobi.service.currency.MerchantSigner;

//卡密直付
public class ChargeOrderService implements ChargeNoticeProcessor {
	private static Logger log = LoggerFactory
			.getLogger(ChargeOrderService.class);
	// 订单结果保留时间,超时检查放在MmochatBattleService.updateSqlAfterBattleThread线程中
	public static final long orderSaveTime = 10 * MmochatConstant.MS_PER_MINUTE;
	// 近期已经写入数据库的订单(结果：成功)：订单号-->处理时间
	public static Map<Long, Long> successOrders = new ConcurrentHashMap<Long, Long>();
	// 近期已经写入数据库的订单(结果：失败)：订单号-->处理时间
	public static Map<Long, Long> failedOrders = new ConcurrentHashMap<Long, Long>();

	private static MerchantSigner merchantSigner = new MerchantSigner();

	// 收到订单结果
	@Override
	public DirectChargeResult dealNotice(DirectChargeNotice notice) {
		log.debug("收到订单通知!");
		String orderIdStr = notice.getOrdreId();
		long orderId;
		if (orderIdStr != null) {
			try {
				orderId = Long.parseLong(orderIdStr);
			} catch (NumberFormatException e) {
				// 订单号不存在
				return DirectChargeResult.order_not_find;
			}
		} else {
			// 订单号不存在
			return DirectChargeResult.order_not_find;
		}
		String reserver1 = notice.getReserved1();
		int roleId;
		try {
			roleId = Integer.parseInt(reserver1);
		} catch (NumberFormatException e) {
			return DirectChargeResult.order_not_find;
		}
		Object lock;
		MmochatPlayer me = null;
		try {
			me = MmochatGmService.getRoleInfoById(roleId);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (me != null) {
			lock = me;
		} else {
			lock = roleId;
		}
		synchronized (lock) {
			if (notice.getResultCode() != ResultCode.SUCCESS) {
				if (failedOrders.get(orderId) != null
						|| successOrders.get(orderId) != null) {
					// 此失败结果已经写入数据库，不再重复执行
					log.debug("订单重复!");
					return DirectChargeResult.order_duplicate;
				}
				// 数据库中此订单设为失败，以备查询
				log.debug("设置订单失败!");
				int updateRowNum = 0;
				try {
					updateRowNum = MmochatDao.setOrderFailed(notice
							.getSkyChargeId(), notice.getRealAmount(), notice
							.getResultDesc(), orderId, roleId);
				} catch (Exception e) {
					log.debug("订单处理时数据库操作异常");
					e.printStackTrace();
					return DirectChargeResult.ok;
				}
				failedOrders.put(orderId, System.currentTimeMillis());
				if (updateRowNum == 0) {
					// 没有找到此订单或此订单已经被设为成功或失败
					// 考虑到没有此订单的机率较小，返回订单重复
					log.debug("订单重复或没有此订单!");
					return DirectChargeResult.order_duplicate;
				} else {
					log.debug("失败订单处理完成!");
					String reason = "充值失败，稍候再试。如果一直失败请拨打0571-87966766查询!"
							+ notice.getResultDesc();
					MmochatGmService.sendKufuPrivateMsg(roleId, reason, true);
					return DirectChargeResult.ok;
				}
			} else {
				// 订单成功
				if (successOrders.get(orderId) != null) {
					// 此成功结果已经写入数据库，不再重复执行
					log.debug("订单重复!");
					return DirectChargeResult.order_duplicate;
				}
				// 到数据库查找是否有此订单(可能服务器重启，而重启是不会加载失败的订单到内存，导致内存中没有此订单)
				// 如果数据库中有此订单且为失败或未处理，则设为成功；如果有订单且为成功，则是重复订单
				// 如果订单成功，则给玩家增加元宝
				log.debug("充值金额为" + notice.getRealAmount() + "分,兑换比率为"
						+ MmochatConstant.getExchangeRate());
				int addValue = MmochatConstant.getExchangeRate()
						* notice.getRealAmount() / 100;
				int addAwardTimes = addValue / MmochatConstant.payValuePerAward;

				try {
					try {
						MmochatPropService.setFirstPayAward(me);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
					boolean success = MmochatDao.setOrderSuccess(notice
							.getSkyChargeId(), notice.getRealAmount(), notice
							.getResultDesc(), orderId, roleId, addValue,
							addAwardTimes, me.getDao(), me.getExp());
					me.setLatest_pay_time(System.currentTimeMillis());
					successOrders.put(orderId, System.currentTimeMillis());
					if (success) {
						try {
							log.debug("成功订单处理完成!");
							if (me != null) {
								log.debug("给玩家内存中增加" + addValue + "元宝!");
								me.addBig_money(addValue);
								me.addRest_award_times(addAwardTimes);
								MmochatStatisticsService.addBigMoneyEarn(
										MmochatBigMoneyEarnType.卡密直付, addValue);
							}
							int payMoney = notice.getRealAmount() / 100;
							String hint = "";
							if (payMoney == 15 || payMoney == 25
									|| payMoney == 45 || payMoney == 95) {
								hint = MmochatUtil
										.wrapColor(
												"(如果您的卡面额为"
														+ (payMoney + 5)
														+ "元，其中5元转成了500K币，"
														+ "K币到账可能需要几分钟。您可以在<K币兑换元宝>项将K币再兑换成元宝)",
												Color.red);
							}
							String content = "您的充值卡充值成功，本次充值"
									+ MmochatUtil.wrapColor(payMoney + "",
											Color.yellow)
									+ "元人民币，获得"
									+ MmochatUtil.wrapColor(addValue + "",
											Color.yellow) + "元宝。";
							if (addAwardTimes != 0) {
								content += "并获得了"
										+ MmochatUtil.wrapColor(addAwardTimes
												+ "", Color.green)
										+ "次充值抽奖活动的机会!";
							}
							content += hint;
							MmochatGmService.sendKufuPrivateMsg(roleId,
									content, true);

							// 记录充值情况
							Integer count = MmochatStatisticsService.todayDirectPayMap
									.get(me.getRoleId());
							if (count == null) {
								// 今日第一次充值
								MmochatStatisticsService.todayDirectPayMap.put(
										me.getRoleId(), notice.getRealAmount());
							} else {
								count += notice.getRealAmount();
								MmochatStatisticsService.todayDirectPayMap.put(
										me.getRoleId(), count);
							}
							MmochatStatisticsService.todayDirectPayTimes++;

							// 即开型充值抽奖
							MmochatPropService.dealFastPayLottery(me, notice
									.getRealAmount());
						} catch (Exception e1) {
							e1.printStackTrace();
						}

						// 给推荐人发放奖励
						try {
							if (me != null && me.getSuggestName() != null
									&& me.getSuggestName().length() > 0) {
								long lifeTime = System.currentTimeMillis()
										- me.getCreateTime();
								int awardCount = 0;
								if (lifeTime < MmochatConstant.MS_PER_DAY * 30) {
									// 创建角色30天以内，奖励20%
									awardCount = notice.getRealAmount() / 5;
								} else if (lifeTime < MmochatConstant.MS_PER_DAY * 60) {
									// 创建角色60天以内，奖励10%
									awardCount = notice.getRealAmount() / 10;
								}
								if (awardCount > 0) {
									String suggestName = me.getSuggestName();
									int suggestRoleId = -1;
									int zoneId = -1;
									boolean ret = false;
									do {
										int index = suggestName.indexOf("区");
										if (index == -1) {
											break;
										}
										String zoneStr = suggestName.substring(
												0, index);
										String suggestRoleIdStr = suggestName
												.substring(index + 1);
										try {
											zoneId = Integer.parseInt(zoneStr);
											suggestRoleId = Integer
													.parseInt(suggestRoleIdStr);
										} catch (NumberFormatException e) {
											break;
										}
										ret = true;
									} while (false);

									// 推荐人格式正确
									if (ret) {
										Integer dstModuleId = MmochatMain
												.getInstanceIdByServerId(zoneId);
										if (dstModuleId != null) {
											// 推荐人与此玩家是同一区服
											if (dstModuleId == MmochatMain
													.getModuleInstID()) {
												// 先在数据库中增加积分
												int row = 0;
												try {
													row = MmochatDao
															.addSuggestScore(
																	awardCount,
																	suggestRoleId);
												} catch (Exception e) {
													e.printStackTrace();
												}
												if (row > 0) {
													MmochatPlayer suggester = MmochatMainService
															.getRoleFromBuffer(suggestRoleId);
													if (suggester != null) {
														// 在线
														suggester
																.addSuggestScore(awardCount);
													}
													// 下发客服消息
													String content1 = MmochatUtil
															.wrapColor("恭喜恭喜!",
																	Color.red)
															+ "您推荐的玩家"
															+ MmochatUtil
																	.wrapColor(
																			me
																					.getName(),
																			Color.green)
															+ "(本区服)在游戏里充值了"
															+ MmochatUtil
																	.wrapColor(
																			notice
																					.getRealAmount()
																					/ 100
																					+ "人民币",
																			Color.yellow)
															+ "，您因此获得了"
															+ MmochatUtil
																	.wrapColor(
																			awardCount
																					+ "积分",
																			Color.yellow)
															+ "的奖励。请再接再励，继续推荐其它朋友一起来玩。";
													MmochatGmService
															.sendKufuPrivateMsg(
																	suggestRoleId,
																	content1,
																	false);
												}
											} else {
												// 跨服发送奖励
												Mmochat_SendSuggestAward pack = new Mmochat_SendSuggestAward();
												pack.setSrcModuleId(MmochatMain
														.getModuleInstID());
												pack
														.setDstModuleId(dstModuleId);
												pack
														.setSuggestRoleId(suggestRoleId);
												pack.setAwardCount(awardCount);
												String zoneName = "";
												if (MmochatMain.getServerName() != null) {
													zoneName = "("
															+ MmochatMain
																	.getServerName()
															+ "区)";
												}
												String content1 = MmochatUtil
														.wrapColor("恭喜恭喜!",
																Color.red)
														+ "您推荐的玩家"
														+ MmochatUtil
																.wrapColor(
																		me
																				.getName(),
																		Color.green)
														+ zoneName
														+ "在游戏里充值了"
														+ MmochatUtil
																.wrapColor(
																		notice
																				.getRealAmount()
																				/ 100
																				+ "人民币",
																		Color.yellow)
														+ "，您因此获得了"
														+ MmochatUtil
																.wrapColor(
																		awardCount
																				+ "积分",
																		Color.yellow)
														+ "的奖励。请再接再励，继续推荐其它朋友一起来玩。";
												pack.setAwardMsg(content1);
												SkymobiHandler handle = MmochatMainService
														.getCommonHandler();
												if (handle != null) {
													handle
															.asyncPushSkymobiModuleMessage(
																	pack, null);
												}
											}
										}
									}
								}
							}
						} catch (Exception e) {
							e.printStackTrace();
						}

						// 本月首次充值活动
						try {
							if (MmochatConstant.isFirstPayThisMonthActivityOpen) {
								MmochatPropEffect effect = me.getPropEffects()
										.get(
												MmochatPropType.本月首次充值增加全属
														.getEffectKey());
								if (effect == null) {
									effect = new MmochatPropEffect();
									effect
											.setPropType(MmochatPropType.本月首次充值增加全属);
									// 效果时间不取道具时间，根据当前时间进行计算，算到本月末
									Calendar date = Calendar.getInstance();
									date.add(Calendar.MONTH, 1);
									date.set(Calendar.DAY_OF_MONTH, 1);
									date.set(Calendar.HOUR_OF_DAY, 0);
									date.set(Calendar.MINUTE, 0);
									date.set(Calendar.SECOND, 0);

									long effectTime = date.getTimeInMillis()
											- System.currentTimeMillis();
									if (effectTime < 0) {
										effectTime = 0;
									}
									effect.setRestAmount(effectTime);
									me.addPropEffect(effect);
									MmochatFriendService
											.sendSystemMsgToPersonByFriendMessage(
													me,
													"这是您本月的首次充值卡充值，恭喜您获得本月期间的"
															+ MmochatUtil
																	.wrapColor(
																			"所有属性+"
																					+ MmochatConstant.attrValueForFirstPayThisMonth,
																			Color.red)
															+ "、"
															+ MmochatUtil
																	.wrapColor(
																			"所有天赋+"
																					+ MmochatConstant.giftValueForFirstPayThisMonth,
																			Color.red)
															+ "的效果。效果在下月消失，下月再次充值可重新激活一个月的效果。");

									// 保存数据库
									List<Object[]> updateObjs = new ArrayList<Object[]>();
									updateObjs.add(new Object[] {
											me.getGson_propEffects(),
											me.getRoleId() });
									try {
										MmochatDao
												.batchUpdateRolePropEffect(updateObjs);
									} catch (Exception e) {
										e.printStackTrace();
									}
								}
							}
						} catch (Exception e) {
							e.printStackTrace();
						}

						// 限时充值抽大奖活动
						if (MmochatPropService.payLotteryInfo != null
								&& MmochatPropService.payLotteryInfo.getState() == MmochatPayLotteryState.开始统计) {
							MmochatPropService.payLotteryInfo.addRolePay(me,
									notice.getRealAmount());
						}

						return DirectChargeResult.ok;
					} else {
						// 没有此订单或此订单已经被设置为成功
						// 考虑到没有此订单的机率较小，返回订单重复
						log.debug("订单重复或没有此订单!");
						return DirectChargeResult.order_duplicate;
					}
				} catch (Exception e) {
					// 数据库响应超时,下次继续处理
					log.debug("订单处理时数据库操作异常");
					e.printStackTrace();
					return DirectChargeResult.app_error;
				}
			}
		}
	}

	// 下发新订单
	public static void sendNewOrder(MmochatPlayer me) {
		if (me == null || me.getUserConnInfo() == null) {
			return;
		}
		if (me.isGuest()) {
			MmochatUtil.sendCommonMsgbox(me, "请先升到6级并正式注册后，再进行充值!");
			return;
		}

		if (MmochatGmService.isStoppingServer()) {
			// 准备停服，不受理订单
			MmochatUtil.sendCommonMsgbox(me, "服务器即将重启，为保证您的数据安全，暂不受理此服务，请见谅。");
			return;
		}

		if (me.getClientVersion() == -1) {
			MmochatUtil.sendCommonMsgbox(me, "请10秒后再充值!");
			return;
		}

		// 创建新订单
		// 1、生成订单号
		long orderId = (new Date()).getTime();
		try {
			// 因为数据库中对orderId作了唯一性保护，所以不必担心orderId重复
			MmochatDao.createNewOrder(orderId, me.getRoleId(), me.getSkyId());
		} catch (Exception e) {
			MmochatUtil.sendCommonMsgbox(me, "当前同时充值人数过多，请重试。");
			return;
		}
		// 2、生成订单签名
		String strMerchantSig;
		int instanceId = MmochatMain.getModuleInstID();
		String reserved1 = me.getRoleId() + "";
		String merchantPasswd, merchantId;
		if (MmochatConstant.workStation == MmochatWorkStationType.斯凯测试
				|| MmochatConstant.workStation == MmochatWorkStationType.青龙自测) {
			merchantPasswd = MmochatConstant.test_merchantPasswd;
			merchantId = MmochatConstant.test_merchantId;
		} else {
			merchantPasswd = MmochatConstant.out_merchantPasswd;
			merchantId = MmochatConstant.out_merchantId;
		}
		try {
			strMerchantSig = merchantSigner
					.getSignature(merchantPasswd, "merchantId", merchantId,
							"appId", MmochatConstant.appId, "instanceID",
							(short) instanceId, "appName",
							MmochatConstant.appName, "skyId", (int) me
									.getSkyId(), "orderId", new String(orderId
									+ ""), "reserved1", reserved1);
		} catch (Exception e) {
			e.printStackTrace();
			MmochatUtil.sendCommonMsgbox(me, "生成订单签名失败，请稍候再试。");
			return;
		}
		// 3、下发订单
		Mmochat_13_13S pack = new Mmochat_13_13S();
		pack.setStrOrdId(new String(orderId + ""));
		pack.setStrMerchantId(merchantId);
		pack.setStrMerchantSig(strMerchantSig);
		pack.setSkyId((int) me.getSkyId());
		pack.setStrRoleName(me.getName());
		pack.setAppId(MmochatConstant.appId);
		pack.setStrAppName(MmochatConstant.appName);
		pack.setAppVer(MmochatConstant.appVer);
		pack.setStrproductId(MmochatConstant.productId);
		pack.setStrProductName(MmochatConstant.productName);
		pack.setExchangeRate(MmochatConstant.getExchangeRate());
		pack.setInstanceId(instanceId);
		pack.setBusinessId(MmochatConstant.businessId);
		pack.setStrBusinessName(MmochatConstant.businessName);
		pack.setPortalId(MmochatConstant.portalId);
		pack.setStrPortalName(MmochatConstant.portalName);
		pack.setReserved1(reserved1);
		MmochatUtil.sendCommonPack(me, pack);

		if (me.getClientVersion() > 3) {
			// 从第4版本开始，增加了此功能
			me.setCanEnterBattle(false);
		}
		log.debug("下发直付订单!");
	}
}
